package api_error

import (
	"app-box/config"
	"encoding/json"
	"errors"
	"fmt"
	"strings"
	"time"

	validator "github.com/go-playground/validator/v10"
)

const (
	TokenOuofDateErrorCode            = 10000
	InvalidTokenErrorCode             = 10001
	RequireLoginErrorCode             = 10002
	UserAlreadyExistErrorCode         = 10003
	PasswordRuleErrorCode             = 10004
	UserNamePasswordNotMatchErrorCode = 10005
	InvalidParametersErrorCode        = 10006
	ApiRequestLimitErrorCode          = 10007
	CASLoginFailedErrorCode           = 10008
	InvalidContentTypeErrorCode       = 10009
	PermissionErrorCode               = 10010
	NotFoundErrorCode                 = 10011
	AppBoxPasswordRequireErrorCode    = 10012
	AppBoxPasswordErrorCode           = 10013
)

func InvalidToken(tokenErr error) ApiErrorType {
	var err = new(
		code(InvalidTokenErrorCode),
		originError(tokenErr),
		message("无效的Token"),
	)
	return err
}

// token过期
func TokenOutOfDate() ApiErrorType {
	var err = new(
		code(TokenOuofDateErrorCode),
		message("登陆超时，请重新登陆"),
	)
	return err
}

// token过期
func RequireLogin() ApiErrorType {
	var err = new(
		code(RequireLoginErrorCode),
		message("请先登陆"),
	)
	return err
}

func UserAlreadyExist() ApiErrorType {
	var err = new(
		code(UserAlreadyExistErrorCode),
		message("用户名已被占用"),
	)
	return err
}

func PasswordRuleError() ApiErrorType {
	var err = new(
		code(PasswordRuleErrorCode),
		message("密码不符合规范"),
	)
	return err
}

func UserNamePasswordNotMatch() ApiErrorType {
	var err = new(
		code(UserNamePasswordNotMatchErrorCode),
		message("用户名密码不匹配"),
	)
	return err
}

func InvalidParameters(err error) ApiErrorType {
	var messageStr = "参数错误"
	if config.NotReleaseMode() {
		var debugMessage = ""
		switch e := err.(type) {
		case validator.ValidationErrors:
			if len(e) > 0 {
				var info []string
				for _, item := range e {
					var str = item.Field() + ": " + item.Tag()
					if p := item.Param(); p != "" {
						str += " " + p
					}
					info = append(info, str)
				}
				debugMessage += strings.Join(info, ", ")
			}
			messageStr += fmt.Sprintf("【参数约束要求：%s】", debugMessage)
		case *json.SyntaxError:
			messageStr += fmt.Sprintf("【Json格式错误：%s】", e.Error())
		default:
			messageStr += fmt.Sprintf("【错误：%s】", e.Error())
		}
	}
	return new(
		message(messageStr),
		code(InvalidParametersErrorCode),
	)
}

func ApiRequestLimitError(duration time.Duration) ApiErrorType {

	var timeStr = strings.Replace(duration.String(), "0m", "", -1)
	timeStr = strings.Replace(timeStr, "0s", "", -1)
	timeStr = strings.Replace(timeStr, "h", "小时", -1)
	timeStr = strings.Replace(timeStr, "m", "分钟", -1)
	timeStr = strings.Replace(timeStr, "s", "秒", -1)
	return new(
		messagef("请求过于频繁，请%s后再试。", timeStr),
		code(ApiRequestLimitErrorCode),
	)
}

func CASLoginFailed(casErrorMessage, casErrorCode string) ApiErrorType {
	return new(
		message("单点登录失败:", casErrorCode),
		code(CASLoginFailedErrorCode),
		originError(errors.New(fmt.Sprintf("CAS Error,Error code:%s, Message:%s", casErrorCode, casErrorMessage))),
	)
}

func InvalidContentTypeError() ApiErrorType {
	return new(
		message("不支持的Content-Type"),
		code(InvalidContentTypeErrorCode),
	)
}
func InvalidFileError() ApiErrorType {
	return new(
		message("文件校验失败"),
		code(InvalidContentTypeErrorCode),
	)
}

func PermissionError() ApiErrorType {
	return new(
		message("权限不足"),
		code(PermissionErrorCode),
	)
}

func NotFound(info ...string) ApiErrorType {
	return new(
		message(info...),
		code(NotFoundErrorCode),
	)
}

func AppBoxPasswordError() ApiErrorType {
	return new(
		message("密码错误"),
		code(AppBoxPasswordErrorCode),
	)
}

func AppBoxPasswordRequireError() ApiErrorType {
	return new(
		message("需要输入密码"),
		code(AppBoxPasswordRequireErrorCode),
	)
}
